<?php

class BcLibBasicOperators implements CliLibrary
{
	private static $operators = array(
		ExpOperator::TYPE_PREFIX => array(
			'+' => array(PREC_PREFIX, 'op_unaryplus', '+p'),
			'-' => array(PREC_PREFIX, 'op_unaryminus', '-p'),
		),
		ExpOperator::TYPE_LEFT => array(
			'*' => array(PREC_TERM, 'op_multiplication'),
			'/' => array(PREC_TERM, 'op_division'),
			'div' => array(PREC_TERM, 'op_intdivision'),
			'%' => array(PREC_TERM, 'op_modulo'),
			'mod' => array(PREC_TERM, 'op_modulo'),
			'+' => array(PREC_SUM, 'op_addition'),
			'-' => array(PREC_SUM, 'op_substraction'),
		),
		ExpOperator::TYPE_RIGHT => array(
			'^' => array(PREC_POWER, 'op_power'),
		)
	);

	public static function addLibrary (CliMode $mode)
	{
		$mode->addOperators(__CLASS__, self::$operators);
	}

	public static function op_unaryplus (ArgContext $args)
	{
		$args->operandCount(1);
		return new BcModeNumber(bcmul('1', $args->toModeNumber(0)->get()));
	}

	public static function op_unaryminus (ArgContext $args)
	{
		$args->operandCount(1);
		return new BcModeNumber(bcmul('-1', $args->toModeNumber(0)->get()));
	}

	public static function op_multiplication (ArgContext $args)
	{
		$args->operandCount(2);
		return new BcModeNumber(bcmul($args->toModeNumber(0)->get(),
			$args->toModeNumber(1)->get()));
	}

	public static function op_division (ArgContext $args)
	{
		$args->operandCount(2);
		return new BcModeNumber(bcdiv($args->toModeNumber(0)->get(),
			$args->toModeNumber(1)->get()));
	}

	public static function op_intdivision (ArgContext $args)
	{
		$args->operandCount(2);
		$result = bcdiv($args->toModeNumber(0)->get(), $args->toModeNumber(1)->get());
		return $args->call('floor', array(new BcModeNumber($result)));
	}

	public static function op_modulo (ArgContext $args)
	{
		$args->operandCount(2);
		return new BcModeNumber(bcmod($args->toModeNumber(0)->get(),
			$args->toModeNumber(1)));
	}

	public static function op_addition (ArgContext $args)
	{
		$args->operandCount(2);
		return new BcModeNumber(bcadd($args->toModeNumber(0)->get(),
			$args->toModeNumber(1)->get()));
	}

	public static function op_substraction (ArgContext $args)
	{
		$args->operandCount(2);
		return new BcModeNumber(bcsub($args->toModeNumber(0)->get(),
			$args->toModeNumber(1)->get()));
	}

	public static function op_power (ArgContext $args)
	{
		$args->operandCount(2);
		return new BcModeNumber(bcpow($args->toModeNumber(0)->get(),
			$args->toModeNumber(1)->get()));
	}
}